import { useAuthStore } from '../app/store/authStore'

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:8000'
const API_PREFIX = '/api/v1'

const redirectToAuth = () => {
  if (typeof window !== 'undefined' && window.location.pathname !== '/auth') {
    window.location.replace('/auth')
  }
}

type RequestOptions = {
  method?: string
  body?: unknown
  headers?: Record<string, string>
  signal?: AbortSignal
}

async function refreshTokens(refreshToken: string) {
  const response = await fetch(`${API_BASE_URL}${API_PREFIX}/auth/refresh`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ refresh_token: refreshToken }),
  })

  if (!response.ok) {
    return null
  }

  const raw = await response.json()
  // 后端统一响应: { code, data }，此处需要解包 data；若直返对象也兼容
  const payload = raw && typeof raw === 'object' && 'data' in raw ? raw.data : raw
  if (!payload || typeof payload !== 'object') return null
  const access_token = (payload as any).access_token
  const refresh_token = (payload as any).refresh_token
  if (typeof access_token === 'string' && typeof refresh_token === 'string') {
    return { access_token, refresh_token }
  }
  return null
}

export async function request<T>(path: string, options: RequestOptions = {}, retry = true): Promise<T> {
  const store = useAuthStore.getState()
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    ...(options.headers ?? {}),
  }

  if (store.accessToken) {
    headers.Authorization = `Bearer ${store.accessToken}`
  }

  const response = await fetch(`${API_BASE_URL}${API_PREFIX}${path}`, {
    method: options.method ?? 'GET',
    headers,
    body: options.body && options.method !== 'GET' ? JSON.stringify(options.body) : undefined,
    signal: options.signal,
  })

  if (response.status === 401) {
    if (retry && store.refreshToken) {
      const newTokens = await refreshTokens(store.refreshToken)
      if (newTokens?.access_token && newTokens?.refresh_token) {
        useAuthStore.getState().setTokens(newTokens)
        return request<T>(path, options, false)
      }
    }
    useAuthStore.getState().logout()
    redirectToAuth()
    throw new Error('需要登录后才能访问')
  }

  if (response.status === 204) {
    return undefined as T
  }

  if (!response.ok) {
    const message = await response.text()
    throw new Error(message || '请求失败')
  }

  const contentType = response.headers.get('Content-Type') ?? ''
  if (!contentType.includes('application/json')) {
    return (await response.text()) as unknown as T
  }

  const json = await response.json()
  if (json && typeof json === 'object' && 'code' in json && 'data' in json) {
    if ((json.code as number) !== 0) {
      throw new Error((json.message as string) || '请求失败')
    }
    return json.data as T
  }
  return json as T
}

export async function requestStream(
  path: string,
  options: RequestOptions & { body?: unknown },
  retry = true,
): Promise<Response> {
  const store = useAuthStore.getState()
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    ...(options.headers ?? {}),
  }

  if (store.accessToken) {
    headers.Authorization = `Bearer ${store.accessToken}`
  }

  const response = await fetch(`${API_BASE_URL}${API_PREFIX}${path}`, {
    method: options.method ?? 'POST',
    headers,
    body: options.body ? JSON.stringify(options.body) : undefined,
    signal: options.signal,
  })

  if (response.status === 401) {
    if (retry && store.refreshToken) {
      const newTokens = await refreshTokens(store.refreshToken)
      if (newTokens?.access_token && newTokens?.refresh_token) {
        useAuthStore.getState().setTokens(newTokens)
        return requestStream(path, options, false)
      }
    }
    useAuthStore.getState().logout()
    redirectToAuth()
    throw new Error('需要登录后才能访问')
  }

  if (!response.ok) {
    const message = await response.text()
    throw new Error(message || '请求失败')
  }

  return response
}
